
#ifndef __RSP_VIEWCONT__HEADER_FILE__
#define __RSP_VIEWCONT__HEADER_FILE__

#include "coid/comm/dynarray.h"
#include "coid/comm/hash/hashkeyset.h"

using namespace coid;

struct OBJLIST_OP {
    enum { OL_INS = 11, OL_DEL = 12, OL_OWN = 13, };
};


////////////////////////////////////////////////////////////////////////////////
template<class T>
struct rsp_view_container
{
    ~rsp_view_container()
    {
        clear();
    }


    T* view_add_or_create( rsp_base* p )
    {
        if( p->oid() != UMAX )  return _views[p->oid()];

        return view_ins(p);
    }

    T* view_set( uint i, rsp_base* p )
    {
        T*& v = _views.get_or_add(i);
        DASSERT( v == 0 );

        v = new T;
        v->set_object(p,i);
        return v;
    }

    void view_del( uint k )
    {
        delete _views[k];
        _views[k] = 0;
    }

    uint view_del( rsp_base* obj )
    {
        uint oid = obj->oid();
        DASSERT( oid != UMAX );

        delete _views[oid];
        _views[oid] = 0;

        //obj->set_oid(UMAX);
        return oid;
    }

    T* view_find( rsp_base* obj ) const
    {
        DASSERT( obj->oid() != UMAX );
        return _views[obj->oid()];
    }

    T* view_ins( rsp_base* p )
    {
        //DASSERT( p->oid() == UMAX );
        T* v = new T;

        //find a free slot
        int i = _views.contains_back(0);
        if(i<0)
        {
            i = _views.size();
            *_views.add() = v;
        }
        else
            _views[i] = v;
    
        //p->set_oid(i);
        v->set_object(p,i);
        return v;
    }


    void clear()
    {
        for( uints i=0; i<_views.size(); ++i )
        {
            T* p = _views[i];
            if(p)
            {
                //p->_oid = UMAX;
                delete p;
                _views[i] = 0;
            }
        }
    }

    dynarray<T*> _views;
};


////////////////////////////////////////////////////////////////////////////////
template<class T>
struct rsp_ref_container
{
    rsp_ref_container() : _hash( extractor(_views) )
    {}

    uint view_add( T* p )
    {
        //find free slot
        int i = _views.contains_back(0);
        if(i<0)
        {
            i = _views.size();
            *_views.add() = p;
        }
        else
            _views[i] = p;

        _hash.insert_value(i);
        return i;
    }

    uint view_set( uint i, T* p, bool reg=true )
    {
        T*& v = _views.get_or_addc(i);
        DASSERT( v == 0 );

        v = p;

        if(reg)
            _hash.insert_value(i);
        return i;
    }

    uint view_del( uint oid, bool destroy )
    {
        const uint* pi = _hash.find_value(oid);
        DASSERT(pi);
        
        _hash.erase(oid);

        if(destroy)
            delete _views[*pi];
        _views[*pi] = 0;
        return *pi;
    }

    void view_del_slot( uint slot, bool destroy )
    {
        T* p = _views[slot];
        _hash.erase( p->oid() );

        if(destroy)
            delete _views[slot];
        _views[slot] = 0;
    }

    T* view_get( uint slot ) const
    {
        return _views[slot];
    }

    T* view_find( uint oid ) const
    {
        const uint* pi = _hash.find_value(oid);
        return pi ? _views[*pi] : 0;
    }

    uint view_find_slot( uint oid ) const
    {
        const uint* pi = _hash.find_value(oid);
        return pi ? *pi : UMAX;
    }

    void view_reg( uint i, rsp_base* p, uint oid )
    {
        _views[i]->set_object(p,oid);
        _hash.insert_or_replace_value(i);
    }
/*
    void view_reg( uint i, uint oid )
    {
        rsp_base* p = _views[i]->object_ptr();
        p->set_oid(oid);
        _hash.insert_or_replace_value(i);
    }
*/
    void view_unreg( uint i )
    {
        _hash.erase_value( _views[i]->oid(), 0 );
    }


    void clear( bool destroy )
    {
        _hash.clear();
        if(destroy) {
            for( uint i=0; i<_views.size(); ++i )
                if( _views[i] )  delete _views[i];
        }
        _views.reset();
    }

    void resize( uint cnt, bool destroy )
    {
        for( uint i=cnt; i<_views.size(); ++i )
            view_del_slot(i,destroy);
            
        _views.needc(cnt);
    }


public:
    struct extractor
    {
        typedef uint    retType;

        extractor( dynarray<T*>& a ) : ex(a)    {}
        uint operator() (uint i) const
        {
            return ex[i]->oid();
        }

        dynarray<T*>& ex;
    };

    ///map oid to index in _views
    hash_keyset< uint, uint, extractor >  _hash;
    dynarray<T*> _views;
};


#endif //__RSP_VIEWCONT__HEADER_FILE__

